<template>
  <!-- vp-raw的作用是隔绝vitepress样式对当前组件的样式影响 -->
  <div class="vp-raw" style="height: 380px">
    <a-table :columns="columns" :data-source="data"> </a-table>
  </div>
</template>
<script lang="ts" setup>
import { SmileOutlined, DownOutlined } from '@ant-design/icons-vue'
import type { TableColumnType } from 'ant-design-vue'
import { ref } from 'vue'

interface ProductInfo {
  key: string
  type: string
  brand: string
  name: string
  price: number
}
const data = ref<ProductInfo[]>([])
function computedRowSpan({
  tableData,
  rowData,
  rowIndex,
  column,
  mutilFields,
}: {
  tableData: ProductInfo[]
  rowData: ProductInfo
  rowIndex?: number
  column?: TableColumnType<ProductInfo>
  mutilFields?: string[]
}) {
  if (undefined === rowIndex || undefined === column) {
    return undefined
  }
  if (tableData === undefined || tableData === null || tableData.length === 0) {
    return undefined
  }
  const dataIndex = column.dataIndex as string
  if (undefined === dataIndex || '' === dataIndex) {
    return undefined
  }
  let rowSpan = 0
  if (!mutilFields || mutilFields.length === 0) {
    rowSpan = doComputedRowSpan(tableData, rowIndex, [dataIndex])
  } else {
    rowSpan = doComputedRowSpan(tableData, rowIndex, mutilFields)
  }
  return rowSpan
}
/**
 * 计算需要合并的行数
 * @param tableData 表格数据
 * @param rowIndex 行索引号
 * @param mutilFields 比较的值字段
 */
function doComputedRowSpan(tableData: ProductInfo[], rowIndex: number, mutilFields: string[]) {
  const cellVal = buildRowVal(tableData, rowIndex, mutilFields)
  if (rowIndex > 0) {
    // 至少是第二行
    let prefixRowIndex = rowIndex - 1
    // 上一行单元格数据
    // @ts-ignore
    const prefixCelVal = buildRowVal(tableData, prefixRowIndex, mutilFields)
    if (prefixCelVal === cellVal) {
      // 当前单元格数据与上一行一至，那么上一行应该完成了行合并
      return 0
    }
  }
  let rowSpan = 0
  let tmpVal: string
  for (let i = rowIndex; i < tableData.length; i++) {
    tmpVal = buildRowVal(tableData, i, mutilFields)
    if (tmpVal === cellVal) {
      rowSpan++
    } else {
      break
    }
  }
  return rowSpan
}
/**
 * 构建比较的值
 * @param tableData 表格数据
 * @param rowIndex 行索引号
 * @param mutilFields 比较的值字段
 */
function buildRowVal(tableData: ProductInfo[], rowIndex: number, mutilFields: string[]) {
  const rowData = tableData[rowIndex]
  let valStr = mutilFields.reduce((prev, cur) => {
    prev += `${rowData[cur]}`
    return prev
  }, '')
  return valStr
}
const columns: TableColumnType<ProductInfo>[] = [
  {
    title: '分类',
    dataIndex: 'type',
    key: 'type',
    customCell: (rowData, rowIndex, column) => {
      return {
        rowSpan: computedRowSpan({ tableData: data.value, rowData, rowIndex, column }),
      }
    },
  },
  {
    title: '品牌',
    dataIndex: 'brand',
    key: 'brand',
    customCell: (rowData, rowIndex, column) => {
      return {
        rowSpan: computedRowSpan({ tableData: data.value, rowData, rowIndex, column,mutilFields:['type','brand'] }),
      }
    },
  },
  {
    title: '商品名',
    dataIndex: 'name',
    key: 'name',
    customCell: (rowData, rowIndex, column) => {
      return {
        rowSpan: computedRowSpan({ tableData: data.value, rowData, rowIndex, column,mutilFields:['type','name'] }),
      }
    },
  },
  {
    title: '价格',
    dataIndex: 'price',
    key: 'price',
    customCell: (rowData, rowIndex, column) => {
      return {
        rowSpan: computedRowSpan({ tableData: data.value, rowData, rowIndex, column,mutilFields:['type','price'] }),
      }
    },
  },
]

setTimeout(() => {
  data.value = [
    {
      key: '1',
      type: '笔记本',
      brand: '联想',
      name: '拯救者Y9000',
      price: 12.5,
    },
    {
      key: '2',
      type: '笔记本',
      brand: '联想',
      name: '拯救者Y7000',
      price: 22.5,
    },
    {
      key: '3',
      type: '笔记本',
      brand: '苹果',
      name: 'MacbookPro',
      price: 22.5,
    },
    {
      key: '4',
      type: '平板',
      brand: '华为',
      name: 'MatePad 2024',
      price: 22.5,
    },
    {
      key: '5',
      type: '平板',
      brand: '华为',
      name: 'MatePad 2023',
      price: 22.5,
    },
  ]
}, 3000)
</script>
